/***************************************************************************
 *   Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com>     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "vsf.h"

static vsf_err_t vsfusbd_UVC_request_prepare(struct vsfusbd_device_t *device)
{
	struct vsfusbd_ctrl_handler_t *ctrl_handler = &device->ctrl_handler;
	struct vsf_buffer_t *buffer = &ctrl_handler->bufstream.mem.buffer;
	struct usb_ctrlrequest_t *request = &ctrl_handler->request;
	uint8_t iface = request->wIndex;
	struct vsfusbd_config_t *config = &device->config[device->configuration];
	struct vsfusbd_UVC_param_t *uvc =
			(struct vsfusbd_UVC_param_t *)config->iface[iface].protocol_param;
	uint8_t tid = request->wIndex, req = request->bRequest;

	switch (request->bRequestType & USB_RECIP_MASK)
	{
	case USB_RECIP_INTERFACE:
		switch (request->bRequestType & USB_TYPE_MASK)
		{
		case USB_TYPE_STANDARD:
			switch (request->bRequest)
			{
			case USB_REQ_SET_INTERFACE:
				break;
			}
			break;
		case USB_TYPE_CLASS:
			buffer->buffer = uvc->reqbuf;
			if (request->wLength > sizeof(uvc->reqbuf))
				return VSFERR_FAIL;

			if (req & USB_UVCREQ_GET)
			{
				if (!uvc->req.get) return VSFERR_FAIL;
				buffer->size = uvc->req.get(uvc, tid, req & 0x0F, uvc->reqbuf);
				if (!buffer->size) return VSFERR_FAIL;
			}
			else
			{
				if (!uvc->req.set) return VSFERR_FAIL;
				switch (req & 0x0F)
				{
				case USB_UVCREQ_CUR:
					buffer->buffer = uvc->reqbuf;
					buffer->size = request->wLength;
					break;
				default:
					return VSFERR_FAIL;
				}
				break;
			}
			break;
		}
		break;
	case USB_RECIP_ENDPOINT:
		break;
	}
	ctrl_handler->data_size = buffer->size;
	return VSFERR_NONE;
}

static vsf_err_t vsfusbd_UVC_request_process(struct vsfusbd_device_t *device)
{
	struct vsfusbd_ctrl_handler_t *ctrl_handler = &device->ctrl_handler;
	struct usb_ctrlrequest_t *request = &ctrl_handler->request;
	uint8_t iface = request->wIndex;
	struct vsfusbd_config_t *config = &device->config[device->configuration];
	struct vsfusbd_UVC_param_t *uvc =
			(struct vsfusbd_UVC_param_t *)config->iface[iface].protocol_param;
	uint8_t tid = request->wIndex, req = request->bRequest;

	switch (request->bRequestType & USB_RECIP_MASK)
	{
	case USB_RECIP_INTERFACE:
		switch (request->bRequestType & USB_TYPE_MASK)
		{
		case USB_TYPE_STANDARD:
			switch (request->bRequest)
			{
			case USB_REQ_SET_INTERFACE:
				break;
			}
			break;
		case USB_TYPE_CLASS:
			if (!(req & USB_UVCREQ_GET))
			{
				switch (req & 0x0F)
				{
				case USB_UVCREQ_CUR:
					uvc->req.set(uvc, tid, req & 0x0F, uvc->reqbuf);
					break;
				default:
					return VSFERR_FAIL;
				}
				break;
			}
			break;
		}
		break;
	case USB_RECIP_ENDPOINT:
		break;
	}
	return VSFERR_NONE;
}

static struct vsfsm_state_t *
vsfusbd_UVC_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
	struct vsfusbd_UVC_param_t *uvc = (struct vsfusbd_UVC_param_t *)sm->user_data;

	switch (evt)
	{
		
	}
	return NULL;
}

static vsf_err_t vsfusbd_UVCVC_class_init(uint8_t iface,
		struct vsfusbd_device_t *device)
{
	struct vsfusbd_config_t *config = &device->config[device->configuration];
	struct vsfusbd_iface_t *ifs = &config->iface[iface];
	struct vsfusbd_UVC_param_t *uvc =
						(struct vsfusbd_UVC_param_t *)ifs->protocol_param;

	ifs->sm.init_state.evt_handler = vsfusbd_UVC_evt_handler;
	uvc->iface = ifs;
	uvc->device = device;
	ifs->sm.user_data = (void*)uvc;
	return vsfsm_init(&ifs->sm);
}

static vsf_err_t vsfusbd_UVCVS_class_init(uint8_t iface,
		struct vsfusbd_device_t *device)
{
	struct vsfusbd_config_t *config = &device->config[device->configuration];
	struct vsfusbd_iface_t *ifs = &config->iface[iface];
	struct vsfusbd_UVC_param_t *uvc =
						(struct vsfusbd_UVC_param_t *)ifs->protocol_param;

	uvc->video_stream->callback_rx.param = uvc;
//	uvc->video_stream->callback_rx.on_inout = vsfusbd_UVC_on_inout;
//	return vsfstream_connect_rx(
}

const struct vsfusbd_class_protocol_t vsfusbd_UVCVC_class =
{
	.request_prepare =	vsfusbd_UVC_request_prepare,
	.request_process =	vsfusbd_UVC_request_process,
	.init =				vsfusbd_UVCVC_class_init,
};

const struct vsfusbd_class_protocol_t vsfusbd_UVCVS_class =
{
	.request_prepare =	vsfusbd_UVC_request_prepare,
	.request_process =	vsfusbd_UVC_request_process,
	.init =				vsfusbd_UVCVS_class_init,
};
